package com.test.a48;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/***
 * 自定义注解实现监听器
 * @author Administrator
 *
 */
@Configuration
public class A48_3 {
    public static void main(String[] args) {
    	 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_3.class);
         context.getBean(MyService.class).doBusiness();
         context.close();
    	   //test2();
    }
    
    /***
     * 代码优化，判断事件类型
     */
    public static void  test2(){
    	   AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_3.class);
           SmsService bean=context.getBean(SmsService.class);
           Method[] methods = SmsService.class.getMethods(); //得到方法列表
           for(Method  method:methods) {
           	if(method.isAnnotationPresent(MyListener.class)) {//判断是否实现了MyListener注解
                   //ApplicationListener监听器的最基础接口
           		ApplicationListener listener =new ApplicationListener() {

   					@Override
   					public void onApplicationEvent(ApplicationEvent event) {
   						Class<?> eventType = method.getParameterTypes()[0];//得到事件类型
   						 if(eventType.isAssignableFrom(event.getClass())) { //判断右边是否可以匹配左边  判断事件类型是否相同
   							  try {
   									method.invoke(bean, event);//执行
   								}  catch (Exception e) {
   									e.printStackTrace();
   								}
   						 }
   						
   					}
   				};
   				context.addApplicationListener(listener); //把监听器加到context中
           	}
           }
           context.getBean(MyService.class).doBusiness();
           context.close(); 
    };
    
    /***
     * 自定义一个事件监听器
     */
  public static void test1(){
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_3.class);
    SmsService bean=context.getBean(SmsService.class);
    Method[] methods = SmsService.class.getMethods(); //得到方法列表
    for(Method  method:methods) {
    	if(method.isAnnotationPresent(MyListener.class)) {//判断是否实现了MyListener注解
            //ApplicationListener监听器的最基础接口
    		ApplicationListener listener =new ApplicationListener() {

				@Override
				public void onApplicationEvent(ApplicationEvent event) {
					 try {
							method.invoke(bean, event);
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (Exception e) {
							e.printStackTrace();
						}
				}
			};
			context.addApplicationListener(listener); //把监听器加到context中
    	}
    }
    context.getBean(MyService.class).doBusiness();
  // context.close(); 
}
    
    /****
     * 通用的自定义事件  
     * SmartInitializingSingleton  单例被初始化后，方法会被回调
     * @param context
     * @return
     */
    @Bean
    public SmartInitializingSingleton smartInitializingSingleton(ConfigurableApplicationContext context) {
        return () -> {
            for (String name : context.getBeanDefinitionNames()) {//得到bean定义
                Object bean = context.getBean(name);  //得到bean对象
                for (Method method : bean.getClass().getMethods()) {//得到方法，遍历 
                    if (method.isAnnotationPresent(MyListener.class)) { //判断是否实现 MyListener注解
                        context.addApplicationListener((event) -> {
                            System.out.println(event);
                            Class<?> eventType = method.getParameterTypes()[0];// 监听器方法需要的事件类型
                            if (eventType.isAssignableFrom(event.getClass())) {//判断类型
                                try {
                                    method.invoke(bean, event);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }
                }
            }
        };
    }

    @Component
    static class MyService {
        private static final Logger log = LoggerFactory.getLogger(MyService.class);
        @Autowired
        private ApplicationEventPublisher publisher; // applicationContext

        public void doBusiness() {
            log.debug("主线业务");
            // 主线业务完成后需要做一些支线业务，下面是问题代码
            publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
        }
    }

    @Component
    static class SmsService {
        private static final Logger log = LoggerFactory.getLogger(SmsService.class);

        @MyListener
        public void listener(MyEvent myEvent) {
            log.debug("发送短信");
        }
    }

    @Component
    static class EmailService {
        private static final Logger log = LoggerFactory.getLogger(EmailService.class);

        @MyListener
        public void listener(MyEvent myEvent) {
            log.debug("发送邮件");
        }
    }

    /***
     * 自定义的注解
     * @author Administrator
     *
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @interface MyListener {
    }

    static class MyEvent extends ApplicationEvent {
        public MyEvent(Object source) {
            super(source);
        }
    }
}